using System;
using JsonTestConsole;
using System.Text;
using System.Collections.Generic;
using System.IO;

namespace TodoSoft.Json
{
	public class Program
	{
		 private static Book bookA = new Book { 
			Title = null,//"Around the world in 80 days",
            Type = BookType.Roman,
            PubDate = new DateTime(1892, 1, 11),
            PagesCount = 200,
            Tags = new List<string> { "travel", "adventure" },
            Author = new Author {
				FirstName = "Jules",
                LastName = "Verne"
            }
        };
		
		public static void Main (string[] args)
		{
			showResults = true;
			
			count = 1;
			
			Test("Todosoft-codegen IL", () => JsonSerializer.Instance.Serialize(Program.bookA));
			
			showResults = false;
			count = 100000;
			Console.WriteLine("serialize testing:");
			Test("StringBuilder", () => SbTest());
			Test("Todosoft-codegen IL", () => JsonSerializer.Instance.Serialize(Program.bookA));
			var act = JsonSerializer.Instance.GetSerializeMethod<Book>();
			Test("Todosoft-codegen IL2", () => {
				var sb = new StringBuilder(256);
				var tw = new StringWriter(sb);
				act(Program.bookA, tw);
			return sb.ToString();});
			
						
			JsonSerializer.Instance.Clear();
			
			Test("Todosoft-codegen Lazy 2", () => {
				var sb = new StringBuilder(256);
				var tw = new StringWriter(sb);
				JsonSerializer.Instance.Serialize(Program.bookA, tw);
				JsonSerializer.Instance.Serialize(Program.bookA.Author, tw);
			return sb.ToString();});
			
			Console.ReadLine();
		}
		
		static bool showResults = false;
		static int count;
		
		private static void Test(string name, Func<string> action)
		{
			var startTime = DateTime.Now;
			string lastResult = "empty";
			for(int i=0; i < count; i++)
				lastResult = action();
			var endTime = DateTime.Now;
			var duration = endTime.Subtract(startTime).TotalMilliseconds;
			Console.WriteLine(name + " " + count + " times duration (ms): " + duration);
					
			if(showResults)
			{
				Console.WriteLine("Last result is:");
				Console.WriteLine(lastResult);
				Console.WriteLine();
			}
		}
		
		static string SbTest()
		{
			var testData = Program.bookA;
			
			StringBuilder sb = new StringBuilder(400);
			
			sb.Append("{ \"Title\":\"");
			if(testData.Title != null)
				sb.Append(testData.Title.Replace("\"","\\\""));
			sb.Append("\", \"Type\":");
			sb.Append((int)testData.Type);
			sb.Append(", \"PubDate\":\"");
			sb.Append(testData.PubDate);
			sb.Append("\", \"PagesCount\":");
			sb.Append(testData.PagesCount);
			
			if(testData.Tags != null && testData.Tags.Count > 0)
			{
				sb.Append(", \"Tags\":[");
				
				sb.Append(testData.Tags[0]);
				
				for(int i=1;i<testData.Tags.Count;i++)
				{
					sb.Append(", "); 
					sb.Append(testData.Tags[i]);
				}
				
				sb.Append("]");
			}
			
			if(testData.Author != null)
			{
				sb.Append(", \"Author\":{\"FirstName\":\"");
				sb.Append(testData.Author.FirstName.Replace("\"","\\\""));
				sb.Append("\", \"LastName\":\"");
				sb.Append(testData.Author.LastName.Replace("\"","\\\""));
				sb.Append("\" } }");	
			}
			
			return sb.ToString();
		}

		public static void Convert(TodoSoft.Json.Author author, TextWriter textWriter)
		{
			textWriter.WriteLine("{");
			textWriter.WriteLine("}");
		}

		public static void Convert(TodoSoft.Json.Book book, TextWriter textWriter)
		{
			Convert(book.Author, textWriter);
		}

		public static void ConvertWriteNonValueProp(TodoSoft.Json.Book book, TextWriter textWriter)
		{
			textWriter.Write(book.PagesCount.ToString());
		}

		public static void ConvertWriteEnum(TodoSoft.Json.Book book, TextWriter textWriter)
		{
			textWriter.Write(((int)book.Type).ToString());
		}

		public class MyClass
		{
			public string Name;
		}

		public static void WriteStringField(MyClass c, TextWriter text)
		{
			text.Write(c.Name);
		}
	}
	
	public enum BookType
    {
        Novel, Roman, Poetry
    }
	
    public class Book
    {
        public string Title { get; set; }
   		public BookType Type { get; set; }
        public DateTime PubDate { get; set; }
        public int PagesCount { get; set; }
        public IList<string> Tags { get; set; }
      	public Author Author { get; set; }
    }

    public class Author
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }
}
